package com
{
	import Box2D.Collision.Shapes.b2CircleShape;
	import Box2D.Collision.Shapes.b2PolygonShape;
	import Box2D.Collision.Shapes.b2Shape;
	import Box2D.Collision.b2AABB;
	import Box2D.Common.Math.b2Vec2;
	import Box2D.Dynamics.b2Body;
	import Box2D.Dynamics.b2BodyDef;
	import Box2D.Dynamics.b2DebugDraw;
	import Box2D.Dynamics.b2Fixture;
	import Box2D.Dynamics.b2FixtureDef;
	import Box2D.Dynamics.b2World;
	
	import flash.display.Sprite;
	import flash.events.Event;

	public class Demo
	{
		public var m_world:b2World;
		
		//1像素1/30
		public var m_physScale:Number = 30;
		public var m_timeStep:Number = 1.0/30.0;
		public var m_velocityIterations:int = 10;
		public var m_positionIterations:int = 10;
		
		// world mouse position
		static public var mouseXWorldPhys:Number;
		static public var mouseYWorldPhys:Number;
		static public var mouseXWorld:Number;
		static public var mouseYWorld:Number;
		static public var _mouseX:Number = 0;
		static public var _mouseY:Number = 0;
		
		private var mousePVec:b2Vec2 = new b2Vec2();
		
		protected var s:Sprite;
		public function Demo(s:Sprite)
		{
			this.s = s;
			// Define the gravity vector
			var gravity:b2Vec2 = new b2Vec2(0.0, 0.0);
			// Construct a world object
			m_world = new b2World(gravity, true);
			//m_world.SetBroadPhase(new b2BroadPhase(worldAABB));
			m_world.SetWarmStarting(true);
			// set debug draw
			var dbgDraw:b2DebugDraw = new b2DebugDraw();
			//var dbgSprite:Sprite = new Sprite();
			//m_sprite.addChild(dbgSprite);
			//设置临时的颜色填充
			dbgDraw.SetSprite(s);
			dbgDraw.SetDrawScale(30.0);
			dbgDraw.SetFillAlpha(0.3);
			dbgDraw.SetLineThickness(1.0);
			dbgDraw.SetFlags(b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit);
			m_world.SetDebugDraw(dbgDraw);
			
			// Create border of boxes
			var wall:b2PolygonShape = new b2PolygonShape();
			var wallBd:b2BodyDef = new b2BodyDef();
			var wallB:b2Body;
			
			//900 * 500
			//左和右
			wall.SetAsBox(getSize(100), getSize(600));//创建一个尺寸
			// Left
			wallBd.position.Set(getPosi(0), getPosi(300));//设置墙体位置
			wallB = m_world.CreateBody(wallBd);//在物理世界中建立墙体
			wallB.CreateFixture2(wall);//设置物理世界中这个墙体的尺寸
			// Right
			wallBd.position.Set(getPosi(1000), getPosi(300));
			wallB = m_world.CreateBody(wallBd);
			wallB.CreateFixture2(wall);
			
			//上和下
			wall.SetAsBox(getSize(1000), getSize(100));
			// Top
			wallBd.position.Set(getPosi(500), getPosi(0));
			wallB = m_world.CreateBody(wallBd);
			wallB.CreateFixture2(wall);
			// Bottom
			wallBd.position.Set(getPosi(500), getPosi(600));
			wallB = m_world.CreateBody(wallBd);
			wallB.CreateFixture2(wall);
			
			//创建一个角色
			var fixtureDef:b2FixtureDef = new b2FixtureDef();
			var bodyDefC:b2BodyDef = new b2BodyDef();
			bodyDefC.type = b2Body.b2_dynamicBody;
			var circShape:b2CircleShape = new b2CircleShape(getSize(30));
			fixtureDef.shape = circShape;
			fixtureDef.density = 10.0;//密度
			fixtureDef.friction = 0.5;//摩擦力
			fixtureDef.restitution = 0.6;//弹力
			bodyDefC.position.Set(getPosi(500), getPosi(200));
			bodyDefC.angle = Math.random() * Math.PI;
			for(var i:uint = 0; i < 5; ++i){
				var body:b2Body = m_world.CreateBody(bodyDefC);
				body.CreateFixture(fixtureDef);
			}
			
			s.stage.addEventListener(Event.ENTER_FRAME, run);
		}
		
		protected function run(e:Event):void{
			m_world.Step(m_timeStep, m_velocityIterations, m_positionIterations);
			m_world.ClearForces();
			m_world.DrawDebugData();
		}
		
		public function GetBodyAtMouse(includeStatic:Boolean = false):b2Body {
			// Make a small box.
			mousePVec.Set(mouseXWorldPhys, mouseYWorldPhys);
			var aabb:b2AABB = new b2AABB();
			aabb.lowerBound.Set(mouseXWorldPhys - 0.001, mouseYWorldPhys - 0.001);
			aabb.upperBound.Set(mouseXWorldPhys + 0.001, mouseYWorldPhys + 0.001);
			var body:b2Body = null;
			var fixture:b2Fixture;
			
			// Query the world for overlapping shapes.
			function GetBodyCallback(fixture:b2Fixture):Boolean
			{
				var shape:b2Shape = fixture.GetShape();
				if (fixture.GetBody().GetType() != b2Body.b2_staticBody || includeStatic)
				{
					var inside:Boolean = shape.TestPoint(fixture.GetBody().GetTransform(), mousePVec);
					if (inside)
					{
						body = fixture.GetBody();
						return false;
					}
				}
				return true;
			}
			m_world.QueryAABB(GetBodyCallback, aabb);
			return body;
		}
		
		public function getSize(value:Number):Number{
			return value / m_physScale / 2;
		}
		public function getPosi(value:Number):Number{
			return value / m_physScale;
		}
	}
}